home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / ruby / 1.8 / erb.rb < prev    next >
Encoding:
Ruby Source  |  2006-02-12  |  19.9 KB  |  827 lines

  1. # = ERB -- Ruby Templating
  2. #
  3. # Author:: Masatoshi SEKI
  4. # Documentation:: James Edward Gray II and Gavin Sinclair
  5. #
  6. # See ERB for primary documentation and ERB::Util for a couple of utility
  7. # routines.
  8. #
  9. # Copyright (c) 1999-2000,2002,2003 Masatoshi SEKI
  10. #
  11. # You can redistribute it and/or modify it under the same terms as Ruby.
  12.  
  13. #
  14. # = ERB -- Ruby Templating
  15. #
  16. # == Introduction
  17. #
  18. # ERB provides an easy to use but powerful templating system for Ruby.  Using
  19. # ERB, actual Ruby code can be added to any plain text document for the
  20. # purposes of generating document information details and/or flow control.
  21. #
  22. # A very simple example is this:
  23. #   require 'erb'
  24. #
  25. #   x = 42
  26. #   template = ERB.new <<-EOF
  27. #     The value of x is: <%= x %>
  28. #   EOF
  29. #   puts template.result(binding)
  30. #
  31. # <em>Prints:</em> The value of x is: 42
  32. #
  33. # More complex examples are given below.
  34. #
  35. #
  36. # == Recognized Tags
  37. #
  38. # ERB recognizes certain tags in the provided template and converts them based
  39. # on the rules below:
  40. #
  41. #   <% Ruby code -- inline with output %>
  42. #   <%= Ruby expression -- replace with result %>
  43. #   <%# comment -- ignored -- useful in testing %>
  44. #   % a line of Ruby code -- treated as <% line %> (optional -- see ERB.new)
  45. #   %% replaced with % if first thing on a line and % processing is used
  46. #   <%% or %%> -- replace with <% or %> respectively
  47. #
  48. # All other text is passed through ERB filtering unchanged.
  49. #
  50. #
  51. # == Options
  52. #
  53. # There are several settings you can change when you use ERB:
  54. # * the nature of the tags that are recognized;
  55. # * the value of <tt>$SAFE</tt> under which the template is run;
  56. # * the binding used to resolve local variables in the template.
  57. #
  58. # See the ERB.new and ERB#result methods for more detail.
  59. #
  60. #
  61. # == Examples
  62. #
  63. # === Plain Text
  64. #
  65. # ERB is useful for any generic templating situation.  Note that in this example, we use the
  66. # convenient "% at start of line" tag, and we quote the template literally with
  67. # <tt>%q{...}</tt> to avoid trouble with the backslash.
  68. #
  69. #   require "erb"
  70. #   
  71. #   # Create template.
  72. #   template = %q{
  73. #     From:  James Edward Gray II <james@grayproductions.net>
  74. #     To:  <%= to %>
  75. #     Subject:  Addressing Needs
  76. #   
  77. #     <%= to[/\w+/] %>:
  78. #   
  79. #     Just wanted to send a quick note assuring that your needs are being
  80. #     addressed.
  81. #   
  82. #     I want you to know that my team will keep working on the issues,
  83. #     especially:
  84. #   
  85. #     <%# ignore numerous minor requests -- focus on priorities %>
  86. #     % priorities.each do |priority|
  87. #       * <%= priority %>
  88. #     % end
  89. #   
  90. #     Thanks for your patience.
  91. #   
  92. #     James Edward Gray II
  93. #   }.gsub(/^  /, '')
  94. #   
  95. #   message = ERB.new(template, 0, "%<>")
  96. #   
  97. #   # Set up template data.
  98. #   to = "Community Spokesman <spokesman@ruby_community.org>"
  99. #   priorities = [ "Run Ruby Quiz",
  100. #                  "Document Modules",
  101. #                  "Answer Questions on Ruby Talk" ]
  102. #   
  103. #   # Produce result.
  104. #   email = message.result
  105. #   puts email
  106. #
  107. # <i>Generates:</i>
  108. #
  109. #   From:  James Edward Gray II <james@grayproductions.net>
  110. #   To:  Community Spokesman <spokesman@ruby_community.org>
  111. #   Subject:  Addressing Needs
  112. #   
  113. #   Community:
  114. #   
  115. #   Just wanted to send a quick note assuring that your needs are being addressed.
  116. #   
  117. #   I want you to know that my team will keep working on the issues, especially:
  118. #   
  119. #       * Run Ruby Quiz
  120. #       * Document Modules
  121. #       * Answer Questions on Ruby Talk
  122. #   
  123. #   Thanks for your patience.
  124. #   
  125. #   James Edward Gray II
  126. #
  127. # === Ruby in HTML
  128. #
  129. # ERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby).  Notice the need in
  130. # this example to provide a special binding when the template is run, so that the instance
  131. # variables in the Product object can be resolved.
  132. #
  133. #   require "erb"
  134. #   
  135. #   # Build template data class.
  136. #   class Product
  137. #     def initialize( code, name, desc, cost )
  138. #       @code = code
  139. #       @name = name
  140. #       @desc = desc
  141. #       @cost = cost
  142. #            
  143. #       @features = [ ]
  144. #     end
  145. #   
  146. #     def add_feature( feature )
  147. #       @features << feature
  148. #     end
  149. #   
  150. #     # Support templating of member data.
  151. #     def get_binding
  152. #       binding
  153. #     end
  154. #   
  155. #     # ...
  156. #   end
  157. #   
  158. #   # Create template.
  159. #   template = %{
  160. #     <html>
  161. #       <head><title>Ruby Toys -- <%= @name %></title></head>
  162. #       <body>
  163. #   
  164. #         <h1><%= @name %> (<%= @code %>)</h1>
  165. #         <p><%= @desc %></p>
  166. #   
  167. #         <ul>
  168. #           <% @features.each do |f| %>
  169. #             <li><b><%= f %></b></li>
  170. #           <% end %>
  171. #         </ul>
  172. #   
  173. #         <p>
  174. #           <% if @cost < 10 %>
  175. #             <b>Only <%= @cost %>!!!</b>
  176. #           <% else %>
  177. #              Call for a price, today!
  178. #           <% end %>
  179. #         </p>
  180. #    
  181. #       </body>
  182. #     </html>
  183. #   }.gsub(/^  /, '')
  184. #   
  185. #   rhtml = ERB.new(template)
  186. #   
  187. #   # Set up template data.
  188. #   toy = Product.new( "TZ-1002",
  189. #                      "Rubysapien",
  190. #                      "Geek's Best Friend!  Responds to Ruby commands...",
  191. #                      999.95 )
  192. #   toy.add_feature("Listens for verbal commands in the Ruby language!")
  193. #   toy.add_feature("Ignores Perl, Java, and all C variants.")
  194. #   toy.add_feature("Karate-Chop Action!!!")
  195. #   toy.add_feature("Matz signature on left leg.")
  196. #   toy.add_feature("Gem studded eyes... Rubies, of course!")
  197. #   
  198. #   # Produce result.
  199. #   rhtml.run(toy.get_binding)
  200. #
  201. # <i>Generates (some blank lines removed):</i>
  202. #
  203. #    <html>
  204. #      <head><title>Ruby Toys -- Rubysapien</title></head>
  205. #      <body>
  206. #    
  207. #        <h1>Rubysapien (TZ-1002)</h1>
  208. #        <p>Geek's Best Friend!  Responds to Ruby commands...</p>
  209. #    
  210. #        <ul>
  211. #            <li><b>Listens for verbal commands in the Ruby language!</b></li>
  212. #            <li><b>Ignores Perl, Java, and all C variants.</b></li>
  213. #            <li><b>Karate-Chop Action!!!</b></li>
  214. #            <li><b>Matz signature on left leg.</b></li>
  215. #            <li><b>Gem studded eyes... Rubies, of course!</b></li>
  216. #        </ul>
  217. #    
  218. #        <p>
  219. #             Call for a price, today!
  220. #        </p>
  221. #    
  222. #      </body>
  223. #    </html>
  224. #
  225. # == Notes
  226. #
  227. # There are a variety of templating solutions available in various Ruby projects:
  228. # * ERB's big brother, eRuby, works the same but is written in C for speed;
  229. # * Amrita (smart at producing HTML/XML);
  230. # * cs/Template (written in C for speed);
  231. # * RDoc, distributed with Ruby, uses its own template engine, which can be reused elsewhere;
  232. # * and others; search the RAA.
  233. #
  234. # Rails, the web application framework, uses ERB to create views.
  235. #
  236. class ERB
  237.   Revision = '$Date: 2006/02/12 15:09:25 $'     #'
  238.  
  239.   # Returns revision information for the erb.rb module.
  240.   def self.version
  241.     "erb.rb [2.0.4 #{ERB::Revision.split[1]}]"
  242.   end
  243. end
  244.  
  245. #--
  246. # ERB::Compiler
  247. class ERB
  248.   class Compiler # :nodoc:
  249.     class PercentLine # :nodoc:
  250.       def initialize(str)
  251.         @value = str
  252.       end
  253.       attr_reader :value
  254.       alias :to_s :value
  255.     end
  256.  
  257.     class Scanner # :nodoc:
  258.       SplitRegexp = /(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>)|(\n)/
  259.  
  260.       @scanner_map = {}
  261.       def self.regist_scanner(klass, trim_mode, percent)
  262.     @scanner_map[[trim_mode, percent]] = klass
  263.       end
  264.  
  265.       def self.default_scanner=(klass)
  266.     @default_scanner = klass
  267.       end
  268.  
  269.       def self.make_scanner(src, trim_mode, percent)
  270.     klass = @scanner_map.fetch([trim_mode, percent], @default_scanner)
  271.     klass.new(src, trim_mode, percent)
  272.       end
  273.  
  274.       def initialize(src, trim_mode, percent)
  275.     @src = src
  276.     @stag = nil
  277.       end
  278.       attr_accessor :stag
  279.  
  280.       def scan; end
  281.     end
  282.  
  283.     class TrimScanner < Scanner # :nodoc:
  284.       TrimSplitRegexp = /(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>\n)|(%>)|(\n)/
  285.  
  286.       def initialize(src, trim_mode, percent)
  287.     super
  288.     @trim_mode = trim_mode
  289.     @percent = percent
  290.     if @trim_mode == '>'
  291.       @scan_line = self.method(:trim_line1)
  292.     elsif @trim_mode == '<>'
  293.       @scan_line = self.method(:trim_line2)
  294.     elsif @trim_mode == '-'
  295.       @scan_line = self.method(:explicit_trim_line)
  296.     else
  297.       @scan_line = self.method(:scan_line)
  298.     end
  299.       end
  300.       attr_accessor :stag
  301.       
  302.       def scan(&block)
  303.     @stag = nil
  304.     if @percent
  305.       @src.each do |line|
  306.         percent_line(line, &block)
  307.       end
  308.     else
  309.       @src.each do |line|
  310.         @scan_line.call(line, &block)
  311.       end
  312.     end
  313.     nil
  314.       end
  315.  
  316.       def percent_line(line, &block)
  317.     if @stag || line[0] != ?%
  318.       return @scan_line.call(line, &block)
  319.     end
  320.  
  321.     line[0] = ''
  322.     if line[0] == ?%
  323.       @scan_line.call(line, &block)
  324.     else
  325.           yield(PercentLine.new(line.chomp))
  326.     end
  327.       end
  328.  
  329.       def scan_line(line)
  330.     line.split(SplitRegexp).each do |token|
  331.       next if token.empty?
  332.       yield(token)
  333.     end
  334.       end
  335.  
  336.       def trim_line1(line)
  337.     line.split(TrimSplitRegexp).each do |token|
  338.       next if token.empty?
  339.       if token == "%>\n"
  340.         yield('%>')
  341.         yield(:cr)
  342.         break
  343.       end
  344.       yield(token)
  345.     end
  346.       end
  347.  
  348.       def trim_line2(line)
  349.     head = nil
  350.     line.split(TrimSplitRegexp).each do |token|
  351.       next if token.empty?
  352.       head = token unless head
  353.       if token == "%>\n"
  354.         yield('%>')
  355.         if  is_erb_stag?(head)
  356.           yield(:cr)
  357.         else
  358.           yield("\n")
  359.         end
  360.         break
  361.       end
  362.       yield(token)
  363.     end
  364.       end
  365.  
  366.       ExplicitTrimRegexp = /(^[ \t]*<%-)|(-%>\n?\z)|(<%-)|(-%>)|(<%%)|(%%>)|(<%=)|(<%#)|(<%)|(%>)|(\n)/
  367.       def explicit_trim_line(line)
  368.     line.split(ExplicitTrimRegexp).each do |token|
  369.       next if token.empty?
  370.       if @stag.nil? && /[ \t]*<%-/ =~ token
  371.         yield('<%')
  372.       elsif @stag && /-%>\n/ =~ token
  373.         yield('%>')
  374.         yield(:cr)
  375.       elsif @stag && token == '-%>'
  376.         yield('%>')
  377.       else
  378.         yield(token)
  379.       end
  380.     end
  381.       end
  382.  
  383.       ERB_STAG = %w(<%= <%# <%)
  384.       def is_erb_stag?(s)
  385.     ERB_STAG.member?(s)
  386.       end
  387.     end
  388.  
  389.     Scanner.default_scanner = TrimScanner
  390.  
  391.     class SimpleScanner < Scanner # :nodoc:
  392.       def scan
  393.     @src.each do |line|
  394.       line.split(SplitRegexp).each do |token|
  395.         next if token.empty?
  396.         yield(token)
  397.       end
  398.     end
  399.       end
  400.     end
  401.     
  402.     Scanner.regist_scanner(SimpleScanner, nil, false)
  403.  
  404.     begin
  405.       require 'strscan'
  406.       class SimpleScanner2 < Scanner # :nodoc:
  407.         def scan
  408.           stag_reg = /(.*?)(<%%|<%=|<%#|<%|\n|\z)/
  409.           etag_reg = /(.*?)(%%>|%>|\n|\z)/
  410.           scanner = StringScanner.new(@src)
  411.           while ! scanner.eos?
  412.             scanner.scan(@stag ? etag_reg : stag_reg)
  413.             text = scanner[1]
  414.             elem = scanner[2]
  415.             yield(text) unless text.empty?
  416.             yield(elem) unless elem.empty?
  417.           end
  418.         end
  419.       end
  420.       Scanner.regist_scanner(SimpleScanner2, nil, false)
  421.  
  422.       class PercentScanner < Scanner # :nodoc:
  423.     def scan
  424.       new_line = true
  425.           stag_reg = /(.*?)(<%%|<%=|<%#|<%|\n|\z)/
  426.           etag_reg = /(.*?)(%%>|%>|\n|\z)/
  427.           scanner = StringScanner.new(@src)
  428.           while ! scanner.eos?
  429.         if new_line && @stag.nil?
  430.           if scanner.scan(/%%/)
  431.         yield('%')
  432.         new_line = false
  433.         next
  434.           elsif scanner.scan(/%/)
  435.         yield(PercentLine.new(scanner.scan(/.*?(\n|\z)/).chomp))
  436.         next
  437.           end
  438.         end
  439.         scanner.scan(@stag ? etag_reg : stag_reg)
  440.             text = scanner[1]
  441.             elem = scanner[2]
  442.             yield(text) unless text.empty?
  443.             yield(elem) unless elem.empty?
  444.         new_line = (elem == "\n")
  445.           end
  446.         end
  447.       end
  448.       Scanner.regist_scanner(PercentScanner, nil, true)
  449.  
  450.       class ExplicitScanner < Scanner # :nodoc:
  451.     def scan
  452.       new_line = true
  453.           stag_reg = /(.*?)(<%%|<%=|<%#|<%-|<%|\n|\z)/
  454.           etag_reg = /(.*?)(%%>|-%>|%>|\n|\z)/
  455.           scanner = StringScanner.new(@src)
  456.           while ! scanner.eos?
  457.         if new_line && @stag.nil? && scanner.scan(/[ \t]*<%-/)
  458.           yield('<%')
  459.           new_line = false
  460.           next
  461.         end
  462.         scanner.scan(@stag ? etag_reg : stag_reg)
  463.             text = scanner[1]
  464.             elem = scanner[2]
  465.         new_line = (elem == "\n")
  466.             yield(text) unless text.empty?
  467.         if elem == '-%>'
  468.           yield('%>')
  469.           if scanner.scan(/(\n|\z)/)
  470.         yield(:cr)
  471.         new_line = true
  472.           end
  473.         elsif elem == '<%-'
  474.           yield('<%')
  475.         else
  476.           yield(elem) unless elem.empty?
  477.         end
  478.           end
  479.         end
  480.       end
  481.       Scanner.regist_scanner(ExplicitScanner, '-', false)
  482.  
  483.     rescue LoadError
  484.     end
  485.  
  486.     class Buffer # :nodoc:
  487.       def initialize(compiler)
  488.     @compiler = compiler
  489.     @line = []
  490.     @script = ""
  491.     @compiler.pre_cmd.each do |x|
  492.       push(x)
  493.     end
  494.       end
  495.       attr_reader :script
  496.  
  497.       def push(cmd)
  498.     @line << cmd
  499.       end
  500.       
  501.       def cr
  502.     @script << (@line.join('; '))
  503.     @line = []
  504.     @script << "\n"
  505.       end
  506.       
  507.       def close
  508.     return unless @line
  509.     @compiler.post_cmd.each do |x|
  510.       push(x)
  511.     end
  512.     @script << (@line.join('; '))
  513.     @line = nil
  514.       end
  515.     end
  516.  
  517.     def compile(s)
  518.       out = Buffer.new(self)
  519.  
  520.       content = ''
  521.       scanner = make_scanner(s)
  522.       scanner.scan do |token|
  523.     if scanner.stag.nil?
  524.       case token
  525.           when PercentLine
  526.         out.push("#{@put_cmd} #{content.dump}") if content.size > 0
  527.         content = ''
  528.             out.push(token.to_s)
  529.             out.cr
  530.       when :cr
  531.         out.cr
  532.       when '<%', '<%=', '<%#'
  533.         scanner.stag = token
  534.         out.push("#{@put_cmd} #{content.dump}") if content.size > 0
  535.         content = ''
  536.       when "\n"
  537.         content << "\n"
  538.         out.push("#{@put_cmd} #{content.dump}")
  539.         out.cr
  540.         content = ''
  541.       when '<%%'
  542.         content << '<%'
  543.       else
  544.         content << token
  545.       end
  546.     else
  547.       case token
  548.       when '%>'
  549.         case scanner.stag
  550.         when '<%'
  551.           if content[-1] == ?\n
  552.         content.chop!
  553.         out.push(content)
  554.         out.cr
  555.           else
  556.         out.push(content)
  557.           end
  558.         when '<%='
  559.           out.push("#{@insert_cmd}((#{content}).to_s)")
  560.         when '<%#'
  561.           # out.push("# #{content.dump}")
  562.         end
  563.         scanner.stag = nil
  564.         content = ''
  565.       when '%%>'
  566.         content << '%>'
  567.       else
  568.         content << token
  569.       end
  570.     end
  571.       end
  572.       out.push("#{@put_cmd} #{content.dump}") if content.size > 0
  573.       out.close
  574.       out.script
  575.     end
  576.  
  577.     def prepare_trim_mode(mode)
  578.       case mode
  579.       when 1
  580.     return [false, '>']
  581.       when 2
  582.     return [false, '<>']
  583.       when 0
  584.     return [false, nil]
  585.       when String
  586.     perc = mode.include?('%')
  587.     if mode.include?('-')
  588.       return [perc, '-']
  589.     elsif mode.include?('<>')
  590.       return [perc, '<>']
  591.     elsif mode.include?('>')
  592.       return [perc, '>']
  593.     else
  594.       [perc, nil]
  595.     end
  596.       else
  597.     return [false, nil]
  598.       end
  599.     end
  600.  
  601.     def make_scanner(src)
  602.       Scanner.make_scanner(src, @trim_mode, @percent)
  603.     end
  604.  
  605.     def initialize(trim_mode)
  606.       @percent, @trim_mode = prepare_trim_mode(trim_mode)
  607.       @put_cmd = 'print'
  608.       @insert_cmd = @put_cmd
  609.       @pre_cmd = []
  610.       @post_cmd = []
  611.     end
  612.     attr_reader :percent, :trim_mode
  613.     attr_accessor :put_cmd, :insert_cmd, :pre_cmd, :post_cmd
  614.   end
  615. end
  616.  
  617. #--
  618. # ERB
  619. class ERB
  620.   #
  621.   # Constructs a new ERB object with the template specified in _str_.
  622.   # 
  623.   # An ERB object works by building a chunk of Ruby code that will output
  624.   # the completed template when run. If _safe_level_ is set to a non-nil value,
  625.   # ERB code will be run in a separate thread with <b>$SAFE</b> set to the
  626.   # provided level.
  627.   # 
  628.   # If _trim_mode_ is passed a String containing one or more of the following
  629.   # modifiers, ERB will adjust its code generation as listed:
  630.   # 
  631.   #     %  enables Ruby code processing for lines beginning with %
  632.   #     <> omit newline for lines starting with <% and ending in %>
  633.   #     >  omit newline for lines ending in %>
  634.   # 
  635.   # _eoutvar_ can be used to set the name of the variable ERB will build up
  636.   # its output in.  This is useful when you need to run multiple ERB
  637.   # templates through the same binding and/or when you want to control where
  638.   # output ends up.  Pass the name of the variable to be used inside a String.
  639.   #
  640.   # === Example
  641.   #
  642.   #  require "erb"
  643.   #  
  644.   #  # build data class
  645.   #  class Listings
  646.   #    PRODUCT = { :name => "Chicken Fried Steak",
  647.   #                :desc => "A well messages pattie, breaded and fried.",
  648.   #                :cost => 9.95 }
  649.   #  
  650.   #    attr_reader :product, :price
  651.   #    
  652.   #    def initialize( product = "", price = "" )
  653.   #      @product = product
  654.   #      @price = price
  655.   #    end
  656.   #    
  657.   #    def build
  658.   #      b = binding
  659.   #      # create and run templates, filling member data variebles
  660.   #      ERB.new(<<-'END_PRODUCT'.gsub(/^\s+/, ""), 0, "", "@product").result b
  661.   #        <%= PRODUCT[:name] %>
  662.   #        <%= PRODUCT[:desc] %>
  663.   #      END_PRODUCT
  664.   #      ERB.new(<<-'END_PRICE'.gsub(/^\s+/, ""), 0, "", "@price").result b
  665.   #        <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %>
  666.   #        <%= PRODUCT[:desc] %>
  667.   #      END_PRICE
  668.   #    end
  669.   #  end
  670.   #  
  671.   #  # setup template data
  672.   #  listings = Listings.new
  673.   #  listings.build
  674.   #  
  675.   #  puts listings.product + "\n" + listings.price
  676.   #
  677.   # _Generates_
  678.   #
  679.   #  Chicken Fried Steak
  680.   #  A well messages pattie, breaded and fried.
  681.   #  
  682.   #  Chicken Fried Steak -- 9.95
  683.   #  A well messages pattie, breaded and fried.
  684.   #  
  685.   def initialize(str, safe_level=nil, trim_mode=nil, eoutvar='_erbout')
  686.     @safe_level = safe_level
  687.     compiler = ERB::Compiler.new(trim_mode)
  688.     set_eoutvar(compiler, eoutvar)
  689.     @src = compiler.compile(str)
  690.     @filename = nil
  691.   end
  692.  
  693.   # The Ruby code generated by ERB
  694.   attr_reader :src
  695.  
  696.   # The optional _filename_ argument passed to Kernel#eval when the ERB code
  697.   # is run
  698.   attr_accessor :filename
  699.  
  700.   #
  701.   # Can be used to set _eoutvar_ as described in ERB#new.  It's probably easier
  702.   # to just use the constructor though, since calling this method requires the
  703.   # setup of an ERB _compiler_ object.
  704.   #
  705.   def set_eoutvar(compiler, eoutvar = '_erbout')
  706.     compiler.put_cmd = "#{eoutvar}.concat"
  707.     compiler.insert_cmd = "#{eoutvar}.concat"
  708.  
  709.     cmd = []
  710.     cmd.push "#{eoutvar} = ''"
  711.     
  712.     compiler.pre_cmd = cmd
  713.  
  714.     cmd = []
  715.     cmd.push(eoutvar)
  716.  
  717.     compiler.post_cmd = cmd
  718.   end
  719.  
  720.   # Generate results and print them. (see ERB#result)
  721.   def run(b=TOPLEVEL_BINDING)
  722.     print self.result(b)
  723.   end
  724.  
  725.   #
  726.   # Executes the generated ERB code to produce a completed template, returning
  727.   # the results of that code.  (See ERB#new for details on how this process can
  728.   # be affected by _safe_level_.)
  729.   # 
  730.   # _b_ accepts a Binding or Proc object which is used to set the context of
  731.   # code evaluation.
  732.   #
  733.   def result(b=TOPLEVEL_BINDING)
  734.     if @safe_level
  735.       th = Thread.start { 
  736.     $SAFE = @safe_level
  737.     eval(@src, b, (@filename || '(erb)'), 1)
  738.       }
  739.       return th.value
  740.     else
  741.       return eval(@src, b, (@filename || '(erb)'), 1)
  742.     end
  743.   end
  744.  
  745.   def def_method(mod, methodname, fname='(ERB)')  # :nodoc:
  746.     mod.module_eval("def #{methodname}\n" + self.src + "\nend\n", fname, 0)
  747.   end
  748.  
  749.   def def_module(methodname='erb')  # :nodoc:
  750.     mod = Module.new
  751.     def_method(mod, methodname)
  752.     mod
  753.   end
  754.  
  755.   def def_class(superklass=Object, methodname='result')  # :nodoc:
  756.     cls = Class.new(superklass)
  757.     def_method(cls, methodname)
  758.     cls
  759.   end
  760. end
  761.  
  762. #--
  763. # ERB::Util
  764. class ERB
  765.   # A utility module for conversion routines, often handy in HTML generation.
  766.   module Util
  767.     public
  768.     #
  769.     # A utility method for escaping HTML tag characters in _s_.
  770.     # 
  771.     #     require "erb"
  772.     #     include ERB::Util
  773.     #     
  774.     #     puts html_escape("is a > 0 & a < 10?")
  775.     # 
  776.     # _Generates_
  777.     # 
  778.     #     is a > 0 & a < 10?
  779.     #
  780.     def html_escape(s)
  781.       s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<")
  782.     end
  783.     alias h html_escape
  784.     module_function :h
  785.     module_function :html_escape
  786.     
  787.     #
  788.     # A utility method for encoding the String _s_ as a URL.
  789.     # 
  790.     #     require "erb"
  791.     #     include ERB::Util
  792.     #     
  793.     #     puts url_encode("Programming Ruby:  The Pragmatic Programmer's Guide")
  794.     # 
  795.     # _Generates_
  796.     # 
  797.     #     Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
  798.     #
  799.     def url_encode(s)
  800.       s.to_s.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
  801.     end
  802.     alias u url_encode
  803.     module_function :u
  804.     module_function :url_encode
  805.   end
  806. end
  807.  
  808. #--
  809. # ERB::DefMethod
  810. class ERB
  811.   module DefMethod  # :nodoc:
  812.     public
  813.     def def_erb_method(methodname, erb)
  814.       if erb.kind_of? String
  815.     fname = erb
  816.     File.open(fname) {|f| erb = ERB.new(f.read) }
  817.     erb.def_method(self, methodname, fname)
  818.       else
  819.     erb.def_method(self, methodname)
  820.       end
  821.     end
  822.     module_function :def_erb_method
  823.   end
  824. end
  825.